MaxPoolFusion

对输入张量执行最大池化操作

\[\text{output}_{b, h_o, w_o, c} = \operatorname{clip}\Bigg( \max_{h_i, w_i \in \mathcal{W}(h_o, w_o)} \Big( \text{input}_{b,\; h_i,\; w_i,\; c} \Big),\; \text{minf},\; \text{maxf} \Bigg)\]

其中,窗口区域 \(\mathcal{W}(h_o, w_o)\) 的定义如下:

\[ \begin{align}\begin{aligned}h_i = h_o \cdot \text{stride}_h - \text{pad}_u + \Delta h\\w_i = w_o \cdot \text{stride}_w - \text{pad}_l + \Delta w\\\Delta h \in [0,\ \text{win}_h - 1],\quad \Delta w \in [0,\ \text{win}_w - 1]\end{aligned}\end{align} \]

有效窗口点满足:

\[0 \le h_i < \text{in}_h,\qquad 0 \le w_i < \text{in}_w\]

原始窗口起点定义为:

\[h_{\text{start}} = h_o \cdot \text{stride}_h - \text{pad}_u\]
\[w_{\text{start}} = w_o \cdot \text{stride}_w - \text{pad}_l\]

合法采样范围为:

\[\Delta h \in \Big[ \max(0,\ -h_{\text{start}}),\; \min(\text{win}_h,\ \text{in}_h - h_{\text{start}}) \Big)\]
\[\Delta w \in \Big[ \max(0,\ -w_{\text{start}}),\; \min(\text{win}_w,\ \text{in}_w - w_{\text{start}}) \Big)\]

最大池化计算:

\[v_{\max} = \max_{\Delta h,\ \Delta w}\; \text{input}_{b,\; h_{\text{start}} + \Delta h,\; w_{\text{start}} + \Delta w,\; c}\]

最终输出:

\[\text{output}_{b, h_o, w_o, c} = \min\big(\max(v_{\max},\ \text{minf}),\ \text{maxf}\big)\]
输入:
  • input - 输入张量指针,采用 NHWC 格式,形状为 \([batch,\ in\_h,\ in\_w,\ channel]\)

  • in_w - 输入张量的宽度 (W)

  • in_h - 输入张量的高度 (H)

  • win_w - 池化窗口的宽度,即窗口在 W 方向的大小

  • win_h - 池化窗口的高度,即窗口在 H 方向的大小

  • output_w - 输出特征图的宽度

  • output_h - 输出特征图的高度

  • batch - 批次大小,即输入中的 batch 数

  • channel - 通道数 C ,每个池化位置都分别对 C 个通道独立执行最大池化与裁剪

  • stride_w - 池化窗口在 W 方向的步长

  • stride_h - 池化窗口在 H 方向的步长

  • pad_l - 输入特征图左侧的填充大小

  • pad_u - 输入特征图上侧的填充大小

  • minf - 输出结果的下界值。池化结果会执行 \(\max(v,\ \text{minf})\)

  • maxf - 输出结果的上界值。池化结果会执行 \(\min(v,\ \text{maxf})\)

  • core_mask - 核心掩码,指定使用的计算核心

输出:
  • output - 输出张量指针,采用 NHWC 格式,形状为 \([batch,\ output\_h,\ output\_w,\ channel]\)

支持平台:

FT78NE MT7004

备注

  • FT78NE 支持fp32, fp64

  • MT7004 支持fp16, fp32

  • 调用时将除 core_mask 外的参数打包通过 long long params 数组传入,顺序为: input, output, in_w, in_h, win_w, win_h, output_w, output_h, batch, channel, stride_w, stride_h, pad_l, pad_u, minf, maxf

共享存储版本:

void hp_maxpool_fusion_s(long long *params, int core_mask)
void fp_maxpool_fusion_s(long long *params, int core_mask)
void dp_maxpool_fusion_s(long long *params, int core_mask)

C调用示例:

 1//FT78NE示例
 2#include <stdio.h>
 3
 4int main(int argc, char* argv[]) {
 5    float* input_ptr = (float*)0xA0000000;
 6    float* output_ptr = (float*)0xB0000000;
 7    float* check_ptr = (float*)0xC0000000;
 8    int in_w = 32;
 9    int in_h = 32;
10    int win_w = 6;
11    int win_h = 6;
12    int batch = 4;
13    int channel = 2;
14    int stride_w = 4;
15    int stride_h = 4;
16    int pad_l = 0;
17    int pad_u = 0;
18    float minf = 0.0f;
19    float maxf = 50.0f;
20
21    // 根据标准公式计算输出尺寸
22    int dividor = in_w + pad_l * 2 - win_w;
23    int output_w = (dividor + stride_w - 1) / stride_w + 1;
24    int dividor2 = in_h + pad_u * 2 - win_h;
25    int output_h = (dividor2 + stride_h - 1) / stride_h + 1;
26
27    long long params[16];
28    params[0] = (long long)input_ptr;
29    params[1] = (long long)output_ptr;
30    params[2] = (long long)in_w;
31    params[3] = (long long)in_h;
32    params[4] = (long long)win_w;
33    params[5] = (long long)win_h;
34    params[6] = (long long)output_w;
35    params[7] = (long long)output_h;
36    params[8] = (long long)batch;
37    params[9] = (long long)channel;
38    params[10] = (long long)stride_w;
39    params[11] = (long long)stride_h;
40    params[12] = (long long)pad_l;
41    params[13] = (long long)pad_u;
42    params[14] = (long long)&minf;
43    params[15] = (long long)&maxf;
44    int core_mask = 0x0f;
45    fp_maxpool_fusion_s(params, core_mask);
46    return 0;
47}

私有存储版本:

void hp_maxpool_fusion_p(long long *params)
void fp_maxpool_fusion_p(long long *params)
void dp_maxpool_fusion_p(long long *params)

C调用示例:

 1//FT78NE示例
 2#include <stdio.h>
 3
 4int main(int argc, char* argv[]) {
 5    float* input_ptr = (float*)0xA0000000;
 6    float* output_ptr = (float*)0xB0000000;
 7    float* check_ptr = (float*)0xC0000000;
 8    int in_w = 32;
 9    int in_h = 32;
10    int win_w = 6;
11    int win_h = 6;
12    int batch = 4;
13    int channel = 2;
14    int stride_w = 4;
15    int stride_h = 4;
16    int pad_l = 0;
17    int pad_u = 0;
18    float minf = 0.0f;
19    float maxf = 50.0f;
20
21    // 根据标准公式计算输出尺寸
22    int dividor = in_w + pad_l * 2 - win_w;
23    int output_w = (dividor + stride_w - 1) / stride_w + 1;
24    int dividor2 = in_h + pad_u * 2 - win_h;
25    int output_h = (dividor2 + stride_h - 1) / stride_h + 1;
26
27    long long params[16];
28    params[0] = (long long)input_ptr;
29    params[1] = (long long)output_ptr;
30    params[2] = (long long)in_w;
31    params[3] = (long long)in_h;
32    params[4] = (long long)win_w;
33    params[5] = (long long)win_h;
34    params[6] = (long long)output_w;
35    params[7] = (long long)output_h;
36    params[8] = (long long)batch;
37    params[9] = (long long)channel;
38    params[10] = (long long)stride_w;
39    params[11] = (long long)stride_h;
40    params[12] = (long long)pad_l;
41    params[13] = (long long)pad_u;
42    params[14] = (long long)&minf;
43    params[15] = (long long)&maxf;
44    fp_maxpool_fusion_p(params);
45    return 0;
46}